package fsm

type Handler func(interface{}) (string, interface{})

type Machine struct {
	startState string
	curState   string
	handlers   map[string]Handler
	endStates  map[string]bool
}

func (machine *Machine) AddState(handleName string, handlerFn Handler) {
	machine.handlers[handleName] = handlerFn
}

func (machine *Machine) AddEndState(endState string) {
	machine.endStates[endState] = true
}

func (machine *Machine) SetStartState(startState string) {
	machine.startState = startState
	machine.curState = startState
}

func (machine *Machine) GetCurState() string {
	return machine.curState
}

func (machine *Machine) Execute(cargo interface{}) {
	if handler, present := machine.handlers[machine.startState]; present {
		for {
			nextState, nextCargo := handler(cargo)
			_, finished := machine.endStates[nextState]
			if finished {
				break
			} else {
				machine.curState = nextState
				handler, present = machine.handlers[nextState]
				cargo = nextCargo
			}
		}
	}
}

func New() *Machine {
	return &Machine{"", "", make(map[string]Handler), make(map[string]bool)}
}
